/**	
*	Drawing an infinite open book : 
	infini par les deux bouts
*/

import ij.ImagePlus;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;

import java.awt.Color;
import java.awt.Polygon;
import java.io.PrintStream;
import java.util.Random;
import java.util.TreeSet;


public class LivreCantor_ extends ImagePlus implements PlugIn {
	private TreeSet<Double> t=new TreeSet<Double>();
	//private int n=6; 
	private PrintStream output;
	private Random gene=new Random();
	private static boolean windows=true; 
	
	
	private void descente(double bi,double bs,int level){
		if(level>=7) {
			int nbp=2; 
			double largeur=(bs-bi)/3;
			for(int i=0;i<nbp;i++)
			t.add(bi+i*largeur/nbp); 
			return; 
		}
		descente(bi,bi+(bs-bi)/3,level+1); 
		descente(bi+2*(bs-bi)/3,bs,level+1); 
	}
	

	public void run(String arg) {
		ImageProcessor primeIP = new ColorProcessor(2000, 2000);
		int R=850; 
		int r=20; 
		int xb=700,xa=1200,yb=1500,ya=1000; 
		int abscisses[]={xa,xb,xb,xa}; 
		int ordonnees[]={ya,yb,yb-R,ya-R};
		Polygon pl;
		
		
		
		float red=0f; 
		float green=0f;
		float blue=0f;
		
		
		Polygon background=new Polygon(new int[]{0,0,2000,2000},new int[]{0,2000,2000,0},4);
		primeIP.setColor(new Color(0.9f,0.9f,0.82f));
		
		primeIP.fillPolygon(background);
		
		primeIP.setLineWidth(5);
		
		// Construire l'ensemble des pages
		
		descente(0,1,0 ); 
		
	
		Double result[]=new Double[t.size()]; 
		t.toArray(result); 
		//for(int i=0;i<result.length;i++) System.out.println(result[i]); 
		
		
		
		double limite=Math.atan(-(xa-xb+0.0)/(ya-yb+0.0));
		/* Illusion de perspective : concerne uniquement l'angle de la 
		 * partie basse du livre
		 */
		double theta=Math.PI/8;
		/* Controler l'aspect ouvert du livre */
		double ouverture=Math.PI/7;
		/* controle de la perspective */
		double coefP=0.72; 
		// Pages de gauche
		double alphaDebut=-Math.PI/2+theta+ouverture;
		double alphaFin=Math.PI/2+theta;
		double alphaCoef=alphaFin-alphaDebut;
		// Largeur de la couverture depassant 
		int epsilon=15; 
		
		System.out.println("--->"+alphaDebut); 
	
		
		try{
			if(!windows)
			output=new PrintStream("/tmp/pages.txt");
			else
				output=new PrintStream("F:/Povray/pages.txt");
			}
			catch(Exception e){System.out.println("Probleme 1 "+e); System.exit(0);}
		
		// Deuxieme de couverture
		abscisses[0]=(int)(xa+r*Math.sin(alphaDebut)); 
		abscisses[1]=(int)(xb+(r+epsilon)*Math.sin(alphaDebut)); 
		abscisses[2]=(int)(xb+(R+r+2*epsilon)*Math.sin(alphaDebut)); 
		abscisses[3]=(int)(xa+(R+r+epsilon)*Math.sin(alphaDebut)*coefP); 
		ordonnees[0]=(int)(ya-r*Math.cos(alphaDebut)); 
		ordonnees[1]=(int)(yb-(r-epsilon)*Math.cos(alphaDebut)); 
		ordonnees[2]=(int)(yb-(R+r+0.8*epsilon)*Math.cos(alphaDebut)); 
		ordonnees[3]=(int)(ya-(R+r+epsilon)*Math.cos(alphaDebut)*coefP);
		
		pl=new Polygon(abscisses,ordonnees,4);
		primeIP.setColor(new Color(0.6f,0.04f,0.04f)); 
		
		primeIP.fillPolygon(pl);
		
		red=1f;
		green=1f;
		blue=1f;
		
		int index=0;
		while((index<t.size())&&(alphaDebut+result[index]*alphaCoef<limite)){
			 double alpha=alphaDebut+result[index]*alphaCoef; 
		
		abscisses[0]=(int)(xa+r*Math.sin(alpha)); 
		abscisses[1]=(int)(xb+r*Math.sin(alpha)); 
		abscisses[2]=(int)(xb+(R+r)*Math.sin(alpha)); 
		abscisses[3]=(int)(xa+(R+r)*Math.sin(alpha)*coefP); 
		ordonnees[0]=(int)(ya-r*Math.cos(alpha)); 
		ordonnees[1]=(int)(yb-r*Math.cos(alpha)); 
		ordonnees[2]=(int)(yb-(R+r)*Math.cos(alpha)); 
		ordonnees[3]=(int)(ya-(R+r)*Math.cos(alpha)*coefP);
		
		pl=new Polygon(abscisses,ordonnees,4);
		primeIP.setColor(Color.DARK_GRAY); 
		primeIP.drawPolygon(pl); 
		primeIP.setColor(new Color(red,green,blue)); 
		primeIP.fillPolygon(pl);
		int ind=1+gene.nextInt(9); 
		output.println("object{pageR"+ind+"  rotate "+alpha/Math.PI*180+"*x}"); 
		index++;
		
		}
	
		
		// Troisieme de couverture
		abscisses[0]=(int)(xa+r*Math.sin(alphaFin)); 
		abscisses[1]=(int)(xb+(r-epsilon)*Math.sin(alphaFin)); 
		abscisses[2]=(int)(xb+(R+r+2*epsilon)*Math.sin(alphaFin)); 
		abscisses[3]=(int)(xa+(R+r+epsilon)*Math.sin(alphaFin)*coefP); 
		ordonnees[0]=(int)(ya-r*Math.cos(alphaFin)); 
		ordonnees[1]=(int)(yb-(r+epsilon)*Math.cos(alphaFin)); 
		ordonnees[2]=(int)(yb-(R+r+4*epsilon)*Math.cos(alphaFin)); 
		ordonnees[3]=(int)(ya-(R+r+epsilon)*Math.cos(alphaFin)*coefP);
		
		pl=new Polygon(abscisses,ordonnees,4);
		primeIP.setColor(new Color(0.6f,0.04f,0.04f)); 
		
		primeIP.fillPolygon(pl);
		
		
		// Pages de droite
		
		index=result.length-1;
		while(alphaDebut+result[index]*alphaCoef>limite){
			 double alpha=alphaDebut+result[index]*alphaCoef; 
		
		abscisses[0]=(int)(xa+r*Math.sin(alpha)); 
		abscisses[1]=(int)(xb+r*Math.sin(alpha)); 
		abscisses[2]=(int)(xb+(R+r)*Math.sin(alpha)); 
		abscisses[3]=(int)(xa+(R+r)*Math.sin(alpha)*coefP); 
		ordonnees[0]=(int)(ya-r*Math.cos(alpha)); 
		ordonnees[1]=(int)(yb-r*Math.cos(alpha)); 
		ordonnees[2]=(int)(yb-(R+r)*Math.cos(alpha)); 
		ordonnees[3]=(int)(ya-(R+r)*Math.cos(alpha)*coefP);
		
		pl=new Polygon(abscisses,ordonnees,4);
		primeIP.setColor(Color.DARK_GRAY); 
		primeIP.drawPolygon(pl); 
		primeIP.setColor(new Color(red,green,blue)); 
		primeIP.fillPolygon(pl);
		int ind=1+gene.nextInt(9); 
		
		output.println("object{page"+ind+"  rotate "+alpha/Math.PI*180+"*x}"); 
		
		index--;
		
		}
		
		
		
		
		
		
		
	
		
		// Tranche avant gauche
		double alpha=-Math.PI/2+theta+ouverture;
		
		abscisses[0]=(int)(xb+(r+epsilon)*Math.sin(alpha)); 
		abscisses[1]=(int)(xb+(R+r+2*epsilon)*Math.sin(alpha)); 
		abscisses[2]=abscisses[1]-15;
		abscisses[3]=abscisses[0]-15;	 
		ordonnees[0]=(int)(yb-(r-epsilon)*Math.cos(alpha)); 
		ordonnees[1]=(int)(yb-(R+r+0.8*epsilon)*Math.cos(alpha)); 
		ordonnees[2]=ordonnees[1]+15;
		ordonnees[3]=ordonnees[0]+15;
		
		pl=new Polygon(abscisses,ordonnees,4);
		primeIP.setColor(new Color(0.12f,0.02f,0.22f)); 
		//primeIP.setColor(Color.BLUE); 
		primeIP.fillPolygon(pl);
		
		// Tranche avant droite	
		
		alpha=Math.PI/2+theta; 
		 
		abscisses[0]=(int)(xb+(r-epsilon)*Math.sin(alpha)); 
		abscisses[1]=(int)(xb+(R+r+2*epsilon)*Math.sin(alpha)); 
		abscisses[2]=abscisses[1]-8;
		abscisses[3]=abscisses[0]-8;
 
		ordonnees[0]=(int)(yb-(r+epsilon)*Math.cos(alpha)); 
		ordonnees[1]=(int)(yb-(R+r+4*epsilon)*Math.cos(alpha)); 
		ordonnees[2]=ordonnees[1]+15;
		ordonnees[3]=ordonnees[0]+15;
		
		pl=new Polygon(abscisses,ordonnees,4);
		primeIP.setColor(new Color(0.12f,0.02f,0.22f)); 
		//primeIP.setColor(Color.BLUE); 
		primeIP.fillPolygon(pl);
		setProcessor("Verifying", primeIP);
		show();
		output.close(); 
	}

	

}
